package com.lungstudio.chequecheck;

import java.math.BigDecimal;
import java.util.Locale;

import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;

import android.support.v7.app.ActionBarActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.SparseArray;
import android.os.Bundle;
import android.widget.EditText;
import android.widget.TextView;


public class MainActivity extends ActionBarActivity {

    private static final String CHEQUE_AMOUND = "CHEQUE_AMOUND";
    private static final String EN_CHEQUE = "EN_CHEQUE";
    private static final String ZH_CHEQUE = "ZH_CHEQUE";

    private static final double UPPERLIMIT = 999999999999.99;

    private double chequeAmount;
    private String enCheque;
    private String zhCheque;
    
    private AdView adView;

    private EditText chequeAmountET;
    private TextView enChequeTV;
    private TextView zhChequeTV;

    private SparseArray<String> enNumberMap;
    private SparseArray<String> zhNumberMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // ads banner
        adView = (AdView) findViewById(R.id.adView);

        AdRequest adRequest = new AdRequest.Builder().build();

        // Start loading the ad in the background.
        adView.loadAd(adRequest);

        if (savedInstanceState == null){
            chequeAmount = 0.0;
            enCheque = "";
            zhCheque = "";
        }
        else {
            chequeAmount = savedInstanceState.getDouble(CHEQUE_AMOUND);
            enCheque = savedInstanceState.getString(EN_CHEQUE);
            zhCheque = savedInstanceState.getString(ZH_CHEQUE);
        }

        chequeAmountET = (EditText) findViewById(R.id.chequeEditText);
        enChequeTV = (TextView) findViewById(R.id.displayHKDollarTextView);
        zhChequeTV = (TextView) findViewById(R.id.zhDisplayHKDollarTextView);

        initializeNumberMap();

        chequeAmountET.addTextChangedListener(chequeAmountListener);

    }

    private TextWatcher chequeAmountListener = new TextWatcher(){

        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                int count) {

            try{
                chequeAmount = Double.parseDouble(s.toString());
            }
            catch(NumberFormatException e){
                chequeAmount = 0.0;
            }
            
            updateDisplayText();

        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
            // TODO Auto-generated method stub
            
        }

        @Override
        public void afterTextChanged(Editable s) {
            // TODO Auto-generated method stub
            
        }
        
    };

    private void initializeNumberMap() {
        enNumberMap = new SparseArray<String>();
        zhNumberMap = new SparseArray<String>();

        enNumberMap.put(1, getString(R.string.one_text));
        enNumberMap.put(2, getString(R.string.two_text));
        enNumberMap.put(3, getString(R.string.three_text));
        enNumberMap.put(4, getString(R.string.four_text));
        enNumberMap.put(5, getString(R.string.five_text));
        enNumberMap.put(6, getString(R.string.six_text));
        enNumberMap.put(7, getString(R.string.seven_text));
        enNumberMap.put(8, getString(R.string.eight_text));
        enNumberMap.put(9, getString(R.string.nine_text));
        enNumberMap.put(10, getString(R.string.ten_text));
        enNumberMap.put(11, getString(R.string.eleven_text));
        enNumberMap.put(12, getString(R.string.twelve_text));
        enNumberMap.put(13, getString(R.string.thirteen_text));
        enNumberMap.put(14, getString(R.string.fourteen_text));
        enNumberMap.put(15, getString(R.string.fifteen_text));
        enNumberMap.put(16, getString(R.string.sixteen_text));
        enNumberMap.put(17, getString(R.string.seventeen_text));
        enNumberMap.put(18, getString(R.string.eighteen_text));
        enNumberMap.put(19, getString(R.string.nineteen_text));
        enNumberMap.put(20, getString(R.string.twenty_text));
        enNumberMap.put(30, getString(R.string.thirty_text));
        enNumberMap.put(40, getString(R.string.forty_text));
        enNumberMap.put(50, getString(R.string.fifty_text));
        enNumberMap.put(60, getString(R.string.sixty_text));
        enNumberMap.put(70, getString(R.string.seventy_text));
        enNumberMap.put(80, getString(R.string.eighty_text));
        enNumberMap.put(90, getString(R.string.ninety_text));
        enNumberMap.put(100, getString(R.string.hundred_text));
        enNumberMap.put(1000, getString(R.string.thousand_text));
        enNumberMap.put(1000000, getString(R.string.million_text));
        enNumberMap.put(1000000000, getString(R.string.billion_text));

        zhNumberMap.put(1, getString(R.string.zh_one_text));
        zhNumberMap.put(2, getString(R.string.zh_two_text));
        zhNumberMap.put(3, getString(R.string.zh_three_text));
        zhNumberMap.put(4, getString(R.string.zh_four_text));
        zhNumberMap.put(5, getString(R.string.zh_five_text));
        zhNumberMap.put(6, getString(R.string.zh_six_text));
        zhNumberMap.put(7, getString(R.string.zh_seven_text));
        zhNumberMap.put(8, getString(R.string.zh_eight_text));
        zhNumberMap.put(9, getString(R.string.zh_nine_text));
        zhNumberMap.put(10, getString(R.string.zh_ten_text));
        zhNumberMap.put(100, getString(R.string.zh_hundred_text));
        zhNumberMap.put(1000, getString(R.string.zh_thousand_text));
        zhNumberMap.put(10000, getString(R.string.zh_ten_thousand_text));
        zhNumberMap.put(100000000, getString(R.string.zh_hundred_million_text));
    }

    private void updateDisplayText(){
        enCheque = getEnglishAmount();
        zhCheque = getChineseAmount();

        enChequeTV.setText(enCheque);
        zhChequeTV.setText(zhCheque);
    }

    private String getEnglishAmount(){
        if (chequeAmount < 0 || chequeAmount > UPPERLIMIT || (new BigDecimal(Double.toString(chequeAmount))).scale() > 2){
            return getString(R.string.invalid_amount);
        }
        else {
            if (Math.round(chequeAmount * 100) % 100 == 0){ // exact number, no decimal
                if (chequeAmount == 0.0) return getString(R.string.zero_dollar);
                else if (chequeAmount == 1.0) return getString(R.string.one_text) + " "  + getString(R.string.dollar_text) + " " + getString(R.string.ending_text);
                else return integerToEnglish(((long) Math.round(chequeAmount * 100)) / 100L, "") + getString(R.string.dollars_text) + " " + getString(R.string.ending_text);
            } else { // contains decimal
                if (chequeAmount < 1.0) return appendEnglishCents((int) (Math.round(chequeAmount * 100) % 100)) + " " + getString(R.string.ending_text);
                else if (chequeAmount < 2.0) return integerToEnglish(((long) Math.round(chequeAmount * 100)) / 100L, "") + getString(R.string.dollar_text) + " "  + getString(R.string.and_text) + " " + appendEnglishCents((int) (Math.round(chequeAmount * 100) % 100)) + " " + getString(R.string.ending_text);
                else return integerToEnglish(((long) Math.round(chequeAmount * 100)) / 100L, "") + getString(R.string.dollars_text) + " "  + getString(R.string.and_text) + " " + appendEnglishCents((int) (Math.round(chequeAmount * 100) % 100)) + " " + getString(R.string.ending_text);
            }
        }
    }

    private String getChineseAmount(){
        if (chequeAmount < 0 || chequeAmount > UPPERLIMIT || (new BigDecimal(Double.toString(chequeAmount))).scale() > 2){
            return getString(R.string.zh_invalid_amount);
        }
        else {
            if (Math.round(chequeAmount * 100) % 100 == 0){ // exact number, no decimal
                if (chequeAmount == 0.0) return getString(R.string.zh_zero_dollar);
                else return integerToChinese(((long) Math.round(chequeAmount * 100)) / 100L, "") + getString(R.string.zh_dollar_text) + getString(R.string.zh_ending_text);
            } else { // contains decimal
                if (chequeAmount < 1.0) return appendChineseCents((int) (Math.round(chequeAmount * 100) % 100)) + getString(R.string.zh_ending_text);
                else return integerToChinese(((long) Math.round(chequeAmount * 100)) / 100L, "") + getString(R.string.zh_dollar_text) + appendChineseCents((int) (Math.round(chequeAmount * 100) % 100)) + getString(R.string.zh_ending_text);
            }
        }
    }

    // recursive function for getting English interpretation of a number
    private String integerToEnglish(long n, String s){
        if (n <= 20) return s + enNumberMap.get((int) n) + " ";
        else if (n < 100) {
            if (n % 10 == 0) return s + enNumberMap.get((int) n / 10 * 10) + " ";
            else return s + enNumberMap.get((int) n / 10 * 10) + "-" + integerToEnglish(n % 10, s).toLowerCase(Locale.US);
        }
        else if (n < 1000) {
            if (n % 100 == 0) return s + enNumberMap.get((int) n / 100) + " " + getString(R.string.hundred_text) + " ";
            else return s + enNumberMap.get((int) n / 100) + " " + getString(R.string.hundred_text) + " " + integerToEnglish(n % 100, s);
        }
        else if (n < 1000000) {
            if (n % 1000 == 0) return s + integerToEnglish(n / 1000, s) + getString(R.string.thousand_text) + " ";
            else return s + integerToEnglish(n / 1000, s) + getString(R.string.thousand_text) + " " + integerToEnglish(n % 1000, s);
        }
        else if (n < 1000000000) {
            if (n % 1000000 == 0) return s + integerToEnglish(n / 1000000, s) + getString(R.string.million_text) + " ";
            else return s + integerToEnglish(n / 1000000, s) + getString(R.string.million_text) + " " + integerToEnglish(n % 1000000, s);
        }
        else {
            if (n % 1000000000 == 0) return s + integerToEnglish(n / 1000000000, s) + getString(R.string.billion_text) + " ";
            else return s + integerToEnglish(n / 1000000000, s) + getString(R.string.billion_text) + " " + integerToEnglish(n % 1000000000, s);
        }

    }

    // recursive function for getting Chinese interpretation of a number
    private String integerToChinese(long n, String s){
        if (n < 10) return s + zhNumberMap.get((int) n);
        else if (n < 100) {
            if ((n % 10 == 0)) return s + zhNumberMap.get((int) n / 10) + getString(R.string.zh_ten_text);
            else return s + zhNumberMap.get((int) n / 10) + getString(R.string.zh_ten_text) + integerToChinese(n % 10, s);
        }
        else if (n < 1000) {
            if (n % 100 == 0) return s + zhNumberMap.get((int) n / 100) + getString(R.string.zh_hundred_text);
            else return s + zhNumberMap.get((int) n / 100) + getString(R.string.zh_hundred_text) + integerToChinese(n % 100, s);
        }
        else if (n < 10000) {
            if (n % 1000 == 0) return s + zhNumberMap.get((int) n / 1000) + getString(R.string.zh_thousand_text);
            else return s + zhNumberMap.get((int) n / 1000) + getString(R.string.zh_thousand_text) + integerToChinese(n % 1000, s);
        }
        else if (n < 100000000) {
            if (n % 10000 == 0) return s + integerToChinese(n / 10000, s) + getString(R.string.zh_ten_thousand_text);
            else return s + integerToChinese(n / 10000, s) + getString(R.string.zh_ten_thousand_text) + integerToChinese(n % 10000, s);
        } else {
            if (n % 100000000 == 0) return s + integerToChinese(n / 100000000, s) + getString(R.string.zh_hundred_million_text);
            else return s + integerToChinese(n / 100000000, s) + getString(R.string.zh_hundred_million_text) + integerToChinese(n % 100000000, s);
        }
    }

    private String appendEnglishCents(int c){
        if (c == 1){
            return enNumberMap.get(c) + " " + getString(R.string.cent_text);
        }
        else if (c <= 20 || c % 10 == 0) {
            return enNumberMap.get(c) + " " + getString(R.string.cents_text);
        }
        else {
            return enNumberMap.get(c / 10 * 10) + "-" + enNumberMap.get(c % 10).toLowerCase(Locale.US) + " " + getString(R.string.cents_text);
        }
    }

    private String appendChineseCents(int c){
        if (c < 10){
            return zhNumberMap.get(c) + getString(R.string.zh_cent_text);
        }
        else if (c % 10 == 0){
            return zhNumberMap.get(c / 10) + getString(R.string.zh_ten_cents_text);
        }
        else {
            return zhNumberMap.get(c / 10) + getString(R.string.zh_ten_cents_text) + zhNumberMap.get(c % 10) + getString(R.string.zh_cent_text);
        }
    }

    protected void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);
        
        outState.putDouble(CHEQUE_AMOUND, chequeAmount);
        outState.putString(EN_CHEQUE, enCheque);
        outState.putString(ZH_CHEQUE, zhCheque);
    }

//    @Override
//    public boolean onCreateOptionsMenu(Menu menu) {
//        // Inflate the menu; this adds items to the action bar if it is present.
//        getMenuInflater().inflate(R.menu.main, menu);
//        return true;
//    }
//
//    @Override
//    public boolean onOptionsItemSelected(MenuItem item) {
//        // Handle action bar item clicks here. The action bar will
//        // automatically handle clicks on the Home/Up button, so long
//        // as you specify a parent activity in AndroidManifest.xml.
//        int id = item.getItemId();
//        if (id == R.id.action_settings) {
//            return true;
//        }
//        return super.onOptionsItemSelected(item);
//    }
}
